package com.lzy.cloud.order.strategy;

import com.lzy.cloud.order.constants.CommonConstants;
import com.lzy.cloud.order.dtos.*;
import com.lzy.cloud.order.dtos.rvcar.CarRentOrderDto;
import com.lzy.cloud.order.remote.*;
import com.lzy.cloud.order.remote.dtos.*;
import com.lzy.cloud.order.request.CarCalendarRequest;
import com.lzy.cloud.order.request.OverInfo;
import com.lzy.cloud.order.request.TimeAndOvertimeBillingRequest;
import com.lzy.cloud.order.service.*;
import com.lzy.cloud.order.utils.CommonUtil;
import com.lzy.framework.core.ensure.Ensure;
import com.lzy.framework.core.output.Result;
import com.lzy.framework.core.utils.DozerUtils;
import com.lzy.framework.core.utils.StringUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Description: 房车租赁订单相关业务
 * @Author:   gyl
 * @Date:     2018/7/6 16:00
 */
@Component("car/rent/order")
public class CarRentOrderImpl implements StrategyOrder<CarRentOrderDto> {

    private static final Logger LOGGER = LoggerFactory.getLogger(CarRentOrderImpl.class);

    @Autowired
    private OrderRuleService orderRuleService;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private OrderInfoDetailService orderInfoDetailService;
    @Autowired
    private OrderInfoCarRentService orderInfoCarRentService;
    @Autowired
    private OrderExpenseItemService orderExpenseItemService;
    @Autowired
    private OrderCarRentMoneyService orderCarRentMoneyService;
    @Autowired
    private OrderCouponLogService orderCouponLogService;
    @Autowired
    private OrderInsuranceHolderService orderInsuranceHolderService;
    @Autowired
    private OrderInsuranceInfoService orderInsuranceInfoService;
    @Autowired
    private OrderStatusHistoryService orderStatusHistoryService;
    @Autowired
    private GoodsApi goodsApi;
    @Autowired
    private ShopApi shopApi;
    @Autowired
    private AccountWalletApi accountWalletApi;
    @Autowired
    private CouponApi couponApi;
    @Autowired
    private CarCalendarApi carCalendarApi;
    @Autowired
    private MemberCouponApi memberCouponApi;

    /**
     * 方法说明：房车租赁订单新增
     * @param    dto 房车租赁订单对象
     * @return     订单支付信息
     * @date        2018/7/6 16:21
     */
    @Override
    public BaseOrderDto createOrder(CarRentOrderDto dto) {
        // 查询车辆信息
//        Result carRentResult = goodsApi.selectById(2,dto.getCarId());
//        CarRentDto carSaleDto = DozerUtils.map(carRentResult.getResult(), CarRentDto.class);
//        Ensure.that(carSaleDto).isNotNull("00000003");
//        dto.setCarName(carSaleDto.getName());

        // TODO 查询车辆手动挡，驾照，床位
        // 处理房车销售订单
        dto = manageCarSale(dto);
        String orderId = dto.getOrderId();

        // 费用明细
        List<OrderExpenseItemDto> orderExpenseItemDtoList = createOrderExpenseItemList(dto);
        dto.setOrderExpenseItemDtoList(orderExpenseItemDtoList);

        // 生成提车码
        dto.setLiftCode(RandomStringUtils.random(8, false, true));

        // TODO 退订规则暂时写死数据，后期改，用商户查询商户规则，再从规则表复制过来
        OrderRuleDto orderRuleDto = new OrderRuleDto();
        orderRuleDto.setOrderId(orderId);
        orderRuleDto.setContent("写死的规则");
        orderRuleDto.setRuleDetail("写死的规则");
        Ensure.that(orderRuleService.create(orderRuleDto)).isGt(0,"00130001");

        // 保存订单
        OrderInfoDto orderInfoDto = DozerUtils.map(dto, OrderInfoDto.class);
        Ensure.that(orderInfoService.create(orderInfoDto)).isTrue("00010002");

        // 保存订单详情
        OrderInfoDetailDto orderInfoDetailDto = DozerUtils.map(dto, OrderInfoDetailDto.class);
        orderInfoDetailDto.setGoodsId(dto.getCarId());
        Ensure.that(orderInfoDetailService.create(orderInfoDetailDto)).isTrue("00080001");

        // 保存房车租赁
        OrderInfoCarRentDto orderInfoCarRentDto = DozerUtils.map(dto, OrderInfoCarRentDto.class);
        Ensure.that(orderInfoCarRentService.create(orderInfoCarRentDto)).isTrue("00070001");

        // 保存订单费用项目明细
        for (OrderExpenseItemDto oeiDto: orderExpenseItemDtoList) {
            oeiDto.setOrderId(orderId);
            Ensure.that(orderExpenseItemService.create(oeiDto)).isGt(0,"00030001");
        }

        // 保存房车租赁的价格明细快照
        List<OrderCarRentMoneyDto> orderCarRentMoneyDtoList = dto.getOrderCarRentMoneyDtoList();
        for (int i = 0; i < orderCarRentMoneyDtoList.size(); i++) {
            Ensure.that(orderCarRentMoneyService.create(orderCarRentMoneyDtoList.get(i))).isGt(0,"00050001");
        }

        if (dto.getInsuranceList() != null && dto.getInsuranceList().size() > 0) {
            // 保存保险主表
            OrderInsuranceInfoDto oiiDto = new OrderInsuranceInfoDto();
            // TODO 暂时写死保险公司id 后面从common_param表获取
            oiiDto.setThirdId("1");
            oiiDto.setOrderId(orderId);
            oiiDto.setUrgentName(dto.getMemberName());
            oiiDto.setUrgentPhone(dto.getMemberPhone());
            oiiDto.setMoneyCount(new BigDecimal(dto.getInsuranceList().size() * dto.getUseCount().intValue() * CommonConstants.INSU_PRICE.intValue()));
            Long oiiId = orderInsuranceInfoService.create(oiiDto);
            Ensure.that(oiiId).isGt(0,"00150001");

            // 保存保险人信息
            for (OrderInsuranceHolderDto insuranceDto: dto.getInsuranceList()) {
                insuranceDto.setInsuranceId(oiiId);
                insuranceDto.setOrderId(orderId);
                insuranceDto.setMoney(new BigDecimal(dto.getUseCount().intValue() * CommonConstants.INSU_PRICE.intValue()));
                insuranceDto.setStartDate(dto.getStartDate());
                insuranceDto.setEndDate(dto.getEndDate());
                Ensure.that(orderInsuranceHolderService.create(insuranceDto)).isGt(0,"00160001");
            }
        }

        // 查询可用卡券
        List<BaseCouponDto> baseCouponDtoList = DozerUtils.maps((List)memberCouponApi.findCarRentByMemberId(dto.getMemberId()).getResult(), CarSaleDto.class);
        dto.setBaseCouponDtoList(baseCouponDtoList);

        return dto;
    }

    @Override
    public PayOrderMoneyDto confirmPay(CarRentOrderDto dto) {
        // 判断是否启用余额支付
        Ensure.that(dto.getBalanceType().equals(1) || dto.getBalanceType().equals(2)).isTrue("08000030");

        OrderInfoDto orderInfoDto = orderInfoService.find(dto.getOrderId());
        dto.setOrderAmount(orderInfoDto.getOrderAmount());
        dto.setMemberId(orderInfoDto.getMemberId());
        dto.setPlatformId(orderInfoDto.getPlatformId());

        // 费用明细
        List<OrderExpenseItemDto> orderExpenseItemDtoList = confirmPayExpenseItemList(dto);

        // 保存订单费用项目明细
        for (OrderExpenseItemDto oeiDto: orderExpenseItemDtoList) {
            oeiDto.setOrderId(dto.getOrderId());
            //  余额，房车券，房车代金券存在就修改，不存在就新增
            if (oeiDto.getType() == CommonConstants.OrderExpenseItemType.DIRECT_AMOUNT
                    || oeiDto.getType() == CommonConstants.OrderExpenseItemType.ONLINE_AMOUNT
                    || oeiDto.getType() == CommonConstants.OrderExpenseItemType.CAR_VOUCHER
                    || oeiDto.getType() == CommonConstants.OrderExpenseItemType.CAR_CASH_VOUCHER) {
                OrderExpenseItemDto searchDto = new OrderExpenseItemDto();
                searchDto.setOrderId(oeiDto.getOrderId());
                searchDto.setType(oeiDto.getType());
                List<OrderExpenseItemDto> searchList = orderExpenseItemService.queryList(searchDto);
                if (searchList.size() > 0) {
                    // 修改
                    oeiDto.setId(searchList.get(0).getId());
                    Ensure.that(orderExpenseItemService.update(oeiDto)).isTrue("00030003");
                    continue;
                }
            }
            // 新增
            Ensure.that(orderExpenseItemService.create(oeiDto)).isGt(0,"00030001");
        }

        // 卡券操作
        if (dto.getCouponList() != null && dto.getCouponList().size() > 0) {
            for (int i = 0; i < dto.getCouponList().size(); i++) {
                // 保存订单中券流向记录
                // 表
                OrderCouponLogDto orderCouponLogDto = new OrderCouponLogDto();
                orderCouponLogDto.setOrderId(dto.getOrderId());
                orderCouponLogDto.setMemberId(dto.getMemberId());
                orderCouponLogDto.setCouponId(dto.getCouponList().get(i));
                orderCouponLogDto.setType(CommonConstants.OrderCouponLogType.BLOCK);
                Ensure.that(orderCouponLogService.create(orderCouponLogDto)).isGt(0,"00040001");

                // 卡券锁定
                BaseCouponDto baseCouponDto = new BaseCouponDto();
                baseCouponDto.setId(dto.getCouponList().get(i));
                baseCouponDto.setLocked(true);
                baseCouponDto.setUpdateUser(dto.getUpdateUser());
                couponApi.update(baseCouponDto).getResult();
            }
        }

        dto.setTicketCount(dto.getCouponList().size());

        // 修改订单
        OrderInfoDto orderInfoDto1 = DozerUtils.map(dto, OrderInfoDto.class);
        Ensure.that(orderInfoService.update(orderInfoDto1)).isTrue("00010002");

        // 修改房车租赁
        OrderInfoCarRentDto orderInfoCarRentDto = DozerUtils.map(dto, OrderInfoCarRentDto.class);
        Ensure.that(orderInfoCarRentService.update(orderInfoCarRentDto)).isTrue("00070001");

        // TODO 发送短信
//        OrderMessageDTO dto = new OrderMessageDTO();
//        dto.setOrderId(orderId);
//        dto.setMinStatus(OrderSatusDesEnum.TOURCARRENT_NO_PAY.getStatus());
//        orderMsgApi.sendMessage(dto);

        // 返回需要支付的订单的信息
        OrderInfoCarRentDto orderInfoCarRentDto2 = orderInfoCarRentService.queryByOrderId(dto.getOrderId());
        PayOrderMoneyDto orderMoneyDTO = new PayOrderMoneyDto();
        orderMoneyDTO.setOrderId(dto.getOrderId());
        orderMoneyDTO.setOrderAmount(dto.getOrderAmount());
        orderMoneyDTO.setType(dto.getType());
        orderMoneyDTO.setStr(orderInfoCarRentDto2.getLiftCode());

        return orderMoneyDTO;
    }

    /**
     * 方法说明：根据订单号查询订单详情
     * @param    orderId 订单号
     * @return    订单基本信息
     * @date        2018/7/6 16:23
     */
    @Override
    public BaseOrderDto selectOrderByOrderId(String orderId) {
        // 订单主表
        OrderInfoDto orderInfoDto = orderInfoService.find(orderId);
        Ensure.that(orderInfoDto).isNotNull("00010007");
        CarRentOrderDto dto = DozerUtils.map(orderInfoDto, CarRentOrderDto.class);

        // 订单详情
        OrderInfoDetailDto orderInfoDetailDto = orderInfoDetailService.find(orderId);
        Ensure.that(orderInfoDetailDto).isNotNull("00080007");
        dto.setGoodsAmount(orderInfoDetailDto.getGoodsAmount());
        dto.setOnline(orderInfoDetailDto.getOnline());
        dto.setSource(orderInfoDetailDto.getSource());
        dto.setSourceId(orderInfoDetailDto.getSourceId());
        dto.setStopPayTime(orderInfoDetailDto.getStopPayTime());
        dto.setCompleteTime(orderInfoDetailDto.getCompleteTime());
        dto.setRemark(orderInfoDetailDto.getRemark());

        // 房车租赁订单
        OrderInfoCarRentDto orderInfoCarRentDto = orderInfoCarRentService.queryByOrderId(orderId);
        Ensure.that(orderInfoCarRentDto).isNotNull("00060007");
        dto.setShopId(orderInfoCarRentDto.getShopId());
        dto.setShopName(orderInfoCarRentDto.getShopName());
        dto.setCarId(orderInfoCarRentDto.getCarId());
        dto.setCarName(orderInfoCarRentDto.getCarName());
        dto.setOrderTotal(orderInfoCarRentDto.getOrderTotal());
        dto.setItemUrl(orderInfoCarRentDto.getItemUrl());
        dto.setTicketCount(orderInfoCarRentDto.getTicketCount());
        dto.setLiftName(orderInfoCarRentDto.getLiftName());
        dto.setLiftPhone(orderInfoCarRentDto.getLiftPhone());
        dto.setIdNumber(orderInfoCarRentDto.getIdNumber());
        dto.setCarStatus(orderInfoCarRentDto.getCarStatus());
        dto.setStartDate(orderInfoCarRentDto.getStartDate());
        dto.setEndDate(orderInfoCarRentDto.getEndDate());
        dto.setDeductibles(orderInfoCarRentDto.getDeductibles());
        dto.setFeeMoney(orderInfoCarRentDto.getFeeMoney());
        dto.setUseCount(orderInfoCarRentDto.getUseCount());
        dto.setLiftCode(orderInfoCarRentDto.getLiftCode());
        dto.setPickTime(orderInfoCarRentDto.getPickTime());
        dto.setReturnTime(orderInfoCarRentDto.getReturnTime());
        dto.setReturnCoupon(orderInfoCarRentDto.getReturnCoupon());
        dto.setUnsubscribeAmount(orderInfoCarRentDto.getUnsubscribeAmount());
        dto.setMemberId(orderInfoCarRentDto.getMemberId());
        dto.setMemberName(orderInfoCarRentDto.getMemberName());
        dto.setMemberPhone(orderInfoCarRentDto.getMemberPhone());

        // 订单费用项目明细
        List<OrderExpenseItemDto> orderExpenseItemDtoList = orderExpenseItemService.queryListByOrderId(orderId);
        Ensure.that(orderExpenseItemDtoList).isNotNull("00030007");
        dto.setOrderExpenseItemDtoList(orderExpenseItemDtoList);

        // 退订规则
        OrderRuleDto orderRuleDto = orderRuleService.queryByOrderId(orderId);
        Ensure.that(orderRuleDto).isNotNull("00130007");
        dto.setOrderRuleDto(orderRuleDto);

        // 保险
        OrderInsuranceInfoDto orderInsuranceInfoDto = orderInsuranceInfoService.queryByOrderId(orderId);
        Ensure.that(orderInsuranceInfoDto).isNotNull("00150007");
        dto.setOrderInsuranceInfoDto(orderInsuranceInfoDto);

        // 投保人
        List<OrderInsuranceHolderDto> orderInsuranceHolderDtoList = orderInsuranceHolderService.queryListByOrderId(orderId);
        Ensure.that(orderInsuranceHolderDtoList).isNotNull("00160007");
        dto.setOrderInsuranceHolderDtoList(orderInsuranceHolderDtoList);

        // 房车租赁的价格明细快照
        OrderCarRentMoneyDto orderCarRentMoneyDto = new OrderCarRentMoneyDto();
        orderCarRentMoneyDto.setOrderId(orderId);
        List<OrderCarRentMoneyDto> orderCarRentMoneyDtoList = orderCarRentMoneyService.queryList(orderCarRentMoneyDto);
        Ensure.that(orderCarRentMoneyDtoList).isNotNull("00130007");
        dto.setOrderCarRentMoneyDtoList(orderCarRentMoneyDtoList);

        // 订单中券流向记录表
        List<OrderCouponLogDto> orderCouponLogDtoList = orderCouponLogService.queryListByOrderId(orderId);
        Ensure.that(orderCouponLogDtoList).isNotNull("00040007");
        dto.setOrderCouponLogDtoList(orderCouponLogDtoList);

        // 订单状态变化记录
        List<OrderStatusHistoryDto> orderStatusHistoryDtoList = orderStatusHistoryService.queryListByOrderId(orderId);
        Ensure.that(orderStatusHistoryDtoList).isNotNull("00170007");
        dto.setOrderStatusHistoryDtoList(orderStatusHistoryDtoList);

        // 车辆
        Result goodsResult = goodsApi.selectById(2, dto.getCarId());
        GoodsDto goodsDto = DozerUtils.map(goodsResult.getResult(), GoodsDto.class);
        Ensure.that(goodsDto).isNotNull("00180007");

        // 店铺
        Result shopResult = shopApi.selectById(dto.getShopId());
        ShopDto shopDto = DozerUtils.map(shopResult.getResult(), ShopDto.class);
        Ensure.that(shopDto).isNotNull("00190007");

        dto.setShopName(shopDto.getName());
        dto.setShopAddress(shopDto.getAddress());
        dto.setShopPhone(shopDto.getCantactPhone());
        dto.setCarImage(goodsDto.getImage());
        dto.setCarParamDtoList(goodsDto.getCarRentDto().getCarParamDtoList());

        return dto;
    }

    @Override
    public Boolean cancel(BaseOrderDto dto) {
        return Boolean.TRUE;
    }

    @Override
    public Boolean confirm(BaseOrderDto dto) {
        return Boolean.TRUE;
    }

    /**
     * 确认支付-房车租赁费用明细list
     *
     * @param dto
     * @return
     */
    private List<OrderExpenseItemDto> confirmPayExpenseItemList(CarRentOrderDto dto) {
        ArrayList<OrderExpenseItemDto> oemDtoList = new ArrayList<>();

        BigDecimal orderAmount = new BigDecimal(0);
        List<Long> idList = dto.getCouponList();
        if (idList != null && idList.size() > 0) {
            // 判断提交的券中是否有已使用的券
            List<BaseCouponDto> couponDtoList = DozerUtils.maps((List)couponApi.findCarRentByIds(idList).getResult(), BaseCouponDto.class);
            Ensure.that(idList.size() == couponDtoList.size()).isTrue("01000004");

            if ((couponDtoList != null) && (couponDtoList.size() > 0)) {
                // 房车租赁的价格明细快照
                OrderCarRentMoneyDto orderCarRentMoneyDto = new OrderCarRentMoneyDto();
                orderCarRentMoneyDto.setOrderId(dto.getOrderId());
                orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.ALL_DAY);
                List<OrderCarRentMoneyDto> orderCarRentMoneyDtoList = orderCarRentMoneyService.queryList(orderCarRentMoneyDto);
                Ensure.that(orderCarRentMoneyDtoList.size() == couponDtoList.size()).isTrue("01000008");

                //房车券金额
                BigDecimal ticketMoney = new BigDecimal(0);
                //房车代金券金额
                BigDecimal agentTicketMoney = new BigDecimal(0);
                //房车券数量
                Integer ticketNumber = 0;
                //房车代金券数量
                Integer agentTicketNumber = 0;
                //房车券(金额)
                List<BigDecimal> priceList = new ArrayList<>();
                //房车代金券（金额）
                List<BigDecimal> agentPriceList = new ArrayList<>();
                //存放档期内的租金
                List<BigDecimal> rentPriceList = new ArrayList<>();

                for (int i = 0; i < couponDtoList.size(); i++) {
                    BaseCouponDto baseCouponDto = couponDtoList.get(i);
                    if (baseCouponDto.getCategory() == CommonConstants.BaseCouponCategory.VOUCHER_TICKET) {
                        // 房车券
                        ticketNumber++;
                        priceList.add(baseCouponDto.getPrice());
                    } else if (baseCouponDto.getCategory() == CommonConstants.BaseCouponCategory.VOUCHER_AGENT_TICKET) {
                        // 房车代金券
                        agentTicketNumber++;
                        agentPriceList.add(baseCouponDto.getPrice());
                    }
                }

                for (int i = 0; i < orderCarRentMoneyDtoList.size(); i++) {
                    rentPriceList.add(orderCarRentMoneyDtoList.get(i).getMoney());
                }

                //房车券抵用租期内最高的租金
                for (int i = 0; i < ticketNumber; i++) {//rentPriceList
                    ticketMoney = new BigDecimal(ticketMoney.doubleValue() + Collections.max(rentPriceList).doubleValue());
                    rentPriceList.remove(Collections.max(rentPriceList));
                }
                //房车代金券使用规则：
                //当代金券的最大金额大于等于租赁最大价格时，抵消最大价格
                //当代金券的最大金额小于租赁最大价格时，抵消部分价格
                for (int j = 0; j < agentTicketNumber; j++) {
                    if (Collections.max(agentPriceList).doubleValue() >= Collections.max(rentPriceList).doubleValue()) {
                        agentTicketMoney = new BigDecimal(agentTicketMoney.doubleValue() + Collections.max(rentPriceList).doubleValue());
                        rentPriceList.remove(Collections.max(rentPriceList));
                        agentPriceList.remove(Collections.max(agentPriceList));
                    } else {
                        agentTicketMoney = new BigDecimal(agentTicketMoney.doubleValue() + Collections.max(agentPriceList).doubleValue());
                        rentPriceList.remove(Collections.max(rentPriceList));
                        agentPriceList.remove(Collections.max(agentPriceList));
                    }
                }

                OrderExpenseItemDto oemDto = new OrderExpenseItemDto();
                oemDto.setType(CommonConstants.OrderExpenseItemType.CAR_VOUCHER);
                oemDto.setNumber(ticketNumber);
                oemDto.setAmount(ticketMoney);
                oemDto.setWay(CommonConstants.OrderExpenseItemWay.DEDUCTIBLE_ITEM);
                oemDtoList.add(oemDto);

                oemDto = new OrderExpenseItemDto();
                oemDto.setType(CommonConstants.OrderExpenseItemType.CAR_CASH_VOUCHER);
                oemDto.setNumber(agentTicketNumber);
                oemDto.setAmount(agentTicketMoney);
                oemDto.setWay(CommonConstants.OrderExpenseItemWay.DEDUCTIBLE_ITEM);
                oemDtoList.add(oemDto);

                orderAmount = dto.getOrderAmount().subtract(ticketMoney).subtract(agentTicketMoney);
            }
        }

        // 用户钱包余额
        BigDecimal directAmount = dto.getDirectAmount();

        // 扣除的余额
        BigDecimal deductBalance = new BigDecimal(0);

        if (dto.getBalanceType().equals(1)) { // 用余额支付
            if (directAmount.compareTo(orderAmount) >= 0) { // 余额直接提现部分 够付
                deductBalance = orderAmount;

                dto.setBalancePaid(orderAmount);
                dto.setOrderAmount(BigDecimal.ZERO);

                // 余额直接提现部分
                OrderExpenseItemDto oemDto = new OrderExpenseItemDto();
                oemDto.setType(CommonConstants.OrderExpenseItemType.DIRECT_AMOUNT);
                oemDto.setAmount(orderAmount);
                oemDto.setWay(CommonConstants.OrderExpenseItemWay.DEDUCTIBLE_ITEM);
                oemDtoList.add(oemDto);
            } else { // 余额直接提现部分 不够付
                deductBalance = directAmount;

                dto.setBalancePaid(directAmount);
                dto.setOrderAmount(orderAmount.subtract(directAmount));

                // 余额直接提现部分
                OrderExpenseItemDto oemDto = new OrderExpenseItemDto();
                oemDto.setType(CommonConstants.OrderExpenseItemType.DIRECT_AMOUNT);
                oemDto.setAmount(directAmount);
                oemDto.setWay(CommonConstants.OrderExpenseItemWay.DEDUCTIBLE_ITEM);
                oemDtoList.add(oemDto);
            }

            // 调用钱包api余额变成冻结金额
            AccountWalletDto accountWalletDto = new AccountWalletDto();
            accountWalletDto.setBalance(deductBalance);
            accountWalletDto.setMemberId(dto.getMemberId());
            accountWalletDto.setPlatformId(dto.getPlatformId());
            boolean accountResult = (Boolean)accountWalletApi.balanceBecomeFrozenAmount(accountWalletDto).getResult();
            Ensure.that(accountResult).isTrue("01000001");
        } else { // 不用余额支付
            dto.setBalancePaid(BigDecimal.ZERO);
        }

        // 在线支付部分
        OrderExpenseItemDto oemDto = new OrderExpenseItemDto();
        oemDto.setType(CommonConstants.OrderExpenseItemType.ONLINE_AMOUNT);
        oemDto.setAmount(dto.getOrderAmount());
        oemDto.setWay(CommonConstants.OrderExpenseItemWay.DEDUCTIBLE_ITEM);
        oemDtoList.add(oemDto);

        return oemDtoList;
    }

    /**
     * 创建订单-房车租赁费用明细list
     *
     * @param dto
     * @return
     */
    private List<OrderExpenseItemDto> createOrderExpenseItemList(CarRentOrderDto dto) {
        ArrayList<OrderExpenseItemDto> oemDtoList = new ArrayList<>();

        if (dto.getMemberId() == null || dto.getStartDate() == null || "".equals(dto.getStartDate()) ||
                dto.getEndDate() == null || "".equals(dto.getEndDate())) {
            String nullObj = null;
            Ensure.that(nullObj).isNotNull("05000034");
        }

        // 计算使用天数
        try {
            Long count = CommonUtil.getDistanceDays(dto.getEndDate(), dto.getStartDate());
            dto.setUseCount(Integer.valueOf(String.valueOf(count)));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 档期计算价格
        String date = dto.getStartDate();

        // 每天价格
        ArrayList<BigDecimal> priceList = new ArrayList<>(dto.getUseCount() + 1);
        for (int i = 0; i < dto.getUseCount() + 1; i++) {
            // 查出每天的档期价格
            CarCalendarRequest request = new CarCalendarRequest();
            request.setDate(StringUtil.substring(date,0,10));
            request.setCarId(dto.getCarId());
            Result result = carCalendarApi.detail(request);
            CarCalendarDto carCalendarDto = DozerUtils.map(result.getResult(),CarCalendarDto.class);
            Ensure.that(carCalendarDto).isNotNull("01000007");
            priceList.add(carCalendarDto.getPrice());

            // 增加一天
            date = CommonUtil.addOneDayForDate(date);
        }

        date = dto.getStartDate();
        String startDate = dto.getStartDate();
        String endDate = dto.getEndDate();

        // 查询有没有空档期，有就占用
        CarCalendarDto carCalendarDto = new CarCalendarDto();
        carCalendarDto.setCarId(dto.getCarId());
        carCalendarDto.setStartDate(startDate);
        carCalendarDto.setEndDate(endDate);
        Result result = carCalendarApi.findEmptyCalendarAndOccupy(carCalendarDto);
        Boolean carCalendarResult = (Boolean) result.getResult();
        Ensure.that(carCalendarResult).isTrue("01000005");

        // 租赁价格
        BigDecimal rentAmount = new BigDecimal(0);

        // 房车租赁的价格明细快照
        List<OrderCarRentMoneyDto> orderCarRentMoneyDtoList = new ArrayList<>();
        for (int i = 0; i < dto.getUseCount() - 1; i++) {
            if (i == dto.getUseCount() - 2) { // 最后一天
                int startHour = Integer.parseInt(startDate.substring(11, 13));
                int endHour = Integer.parseInt(endDate.substring(11, 13));
                if (startHour >= endHour) { // 24小时 或 24小时之内
                    OrderCarRentMoneyDto orderCarRentMoneyDto = new OrderCarRentMoneyDto();
                    orderCarRentMoneyDto.setOrderId(dto.getOrderId());
                    orderCarRentMoneyDto.setStartTime(startDate);
                    orderCarRentMoneyDto.setEndTime(endDate);
                    orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.ALL_DAY);
                    // 超过12:00算明天价格
                    if (startHour >= 12) {
                        orderCarRentMoneyDto.setMoney(priceList.get(i+1));
                        rentAmount = rentAmount.add(priceList.get(i+1));
                    } else {
                        orderCarRentMoneyDto.setMoney(priceList.get(i));
                        rentAmount = rentAmount.add(priceList.get(i));
                    }
                    orderCarRentMoneyDtoList.add(orderCarRentMoneyDto);
                } else { // 超过24小时
                    OrderCarRentMoneyDto orderCarRentMoneyDto = new OrderCarRentMoneyDto();
                    orderCarRentMoneyDto.setOrderId(dto.getOrderId());
                    orderCarRentMoneyDto.setStartTime(startDate);
                    orderCarRentMoneyDto.setEndTime(CommonUtil.addOneDayFotTime(startDate));
                    orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.ALL_DAY);
                    // 超过12:00算明天价格
                    if (startHour >= 12) {
                        orderCarRentMoneyDto.setMoney(priceList.get(i+1));
                        rentAmount = rentAmount.add(priceList.get(i+1));
                    } else {
                        orderCarRentMoneyDto.setMoney(priceList.get(i));
                        rentAmount = rentAmount.add(priceList.get(i));
                    }
                    orderCarRentMoneyDtoList.add(orderCarRentMoneyDto);

                    int overTime = endHour - startHour;
                    if (overTime > 4) { // 4小时以上算整天
                        orderCarRentMoneyDto = new OrderCarRentMoneyDto();
                        orderCarRentMoneyDto.setOrderId(dto.getOrderId());
                        orderCarRentMoneyDto.setStartTime(CommonUtil.addOneDayFotTime(startDate));
                        orderCarRentMoneyDto.setEndTime(endDate);
                        orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.ALL_DAY);
                        orderCarRentMoneyDto.setMoney(priceList.get(i+1));
                        rentAmount = rentAmount.add(priceList.get(i+1));
                        orderCarRentMoneyDtoList.add(orderCarRentMoneyDto);
                    } else {
                        TimeAndOvertimeBillingRequest request = new TimeAndOvertimeBillingRequest();
                        request.setShopId(dto.getShopId());
                        request.setSourceType(1);
                        request.setSourceId(dto.getCarId());
                        List<OverInfo> overInfos = new ArrayList<>();
                        OverInfo overInfo = new OverInfo();
                        overInfo.setOverTime(overTime);
                        overInfos.add(overInfo);
                        request.setOverInfos(overInfos);

                        orderCarRentMoneyDto = new OrderCarRentMoneyDto();
                        orderCarRentMoneyDto.setOrderId(dto.getOrderId());
                        orderCarRentMoneyDto.setStartTime(CommonUtil.addOneDayFotTime(startDate));
                        orderCarRentMoneyDto.setEndTime(endDate);
                        Object result2 = carCalendarApi.findOverTimePrice(request).getResult();
                        if (result2 == null ) { // 没查到算整天价格
                            orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.ALL_DAY);
                            orderCarRentMoneyDto.setMoney(priceList.get(i+1));
                            rentAmount = rentAmount.add(priceList.get(i+1));
                        } else { // 查到算超时价格
                            OvertimeBillingDto overtimeBillingDto = DozerUtils.map(result2, OvertimeBillingDto.class);
                            orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.TIMEOUT);
                            orderCarRentMoneyDto.setMoney(overtimeBillingDto.getOverFee());
                            rentAmount = rentAmount.add(overtimeBillingDto.getOverFee());
                        }
                        orderCarRentMoneyDtoList.add(orderCarRentMoneyDto);
                    }
                }
            } else {
                OrderCarRentMoneyDto orderCarRentMoneyDto = new OrderCarRentMoneyDto();
                orderCarRentMoneyDto.setOrderId(dto.getOrderId());
                orderCarRentMoneyDto.setStartTime(startDate);
                orderCarRentMoneyDto.setEndTime(CommonUtil.addOneDayFotTime(startDate));
                orderCarRentMoneyDto.setType(CommonConstants.OrderCarRentMoneyType.ALL_DAY);
                // 超过12:00算明天价格
                int startHour = Integer.parseInt(startDate.substring(11, 13));
                if (startHour >= 12) {
                    orderCarRentMoneyDto.setMoney(priceList.get(i+1));
                    rentAmount = rentAmount.add(priceList.get(i+1));
                } else {
                    orderCarRentMoneyDto.setMoney(priceList.get(i));
                    rentAmount = rentAmount.add(priceList.get(i));
                }
                orderCarRentMoneyDtoList.add(orderCarRentMoneyDto);
            }
            // 增加一天
            startDate = CommonUtil.addOneDayFotTime(startDate);
        }
        dto.setOrderCarRentMoneyDtoList(orderCarRentMoneyDtoList);


        //1.3 TODO 不计免赔服务费用
        BigDecimal franchiseMoney = dto.getFeeMoney();
        OrderExpenseItemDto oemDto = new OrderExpenseItemDto();
        oemDto.setType(CommonConstants.OrderExpenseItemType.FRANCHISE_MONEY);
        oemDto.setAmount(franchiseMoney);
        oemDto.setWay(CommonConstants.OrderExpenseItemWay.CHARGE_ITEM);
        oemDtoList.add(oemDto);

        // 平台服务费
        // 平台服务费不适用于微信端
        BigDecimal platFormFee = dto.getPlatFormFee();
        if (CommonConstants.OrderSource.WECHAT_APPLET_FREE.equals(dto.getSource())
                || CommonConstants.OrderSource.WECHAT_APPLET_BUY.equals(dto.getSource())) {
            platFormFee = new BigDecimal(0);
        }
        oemDto = new OrderExpenseItemDto();
        oemDto.setType(CommonConstants.OrderExpenseItemType.PLATFORM);
        oemDto.setAmount(platFormFee);
        oemDto.setWay(CommonConstants.OrderExpenseItemWay.CHARGE_ITEM);
        oemDtoList.add(oemDto);

        //2.保险总金额:暂定为每人每天10元
        BigDecimal insuranceCount = new BigDecimal(0);
        if (dto.getInsuranceList() != null && dto.getInsuranceList().size() >0 ) {
            insuranceCount = new BigDecimal(dto.getInsuranceList().size() * dto.getUseCount().intValue() * CommonConstants.INSU_PRICE.intValue());
            oemDto = new OrderExpenseItemDto();
            oemDto.setType(CommonConstants.OrderExpenseItemType.INSURANCE);
            oemDto.setAmount(insuranceCount);
            oemDto.setWay(CommonConstants.OrderExpenseItemWay.CHARGE_ITEM);
            oemDtoList.add(oemDto);
        }

        //4.订单总金额 = 商品总价格 + 平台服务费 + 保险总费用 + 不计免赔服务费用
        BigDecimal orderAmount = rentAmount.add(platFormFee).add(insuranceCount).add(franchiseMoney);
        dto.setOrderTotal(orderAmount);
        dto.setOrderAmount(orderAmount);
        dto.setGoodsAmount(orderAmount);

        // 商品总价
        oemDto = new OrderExpenseItemDto();
        oemDto.setType(CommonConstants.OrderExpenseItemType.TOTAL_PRICE);
        oemDto.setAmount(rentAmount);
        oemDto.setWay(CommonConstants.OrderExpenseItemWay.CHARGE_ITEM);
        oemDtoList.add(oemDto);

        return oemDtoList;
    }

    /**
     * 处理房车销售订单
     * @param dto
     * @return
     */
    private CarRentOrderDto manageCarSale(CarRentOrderDto dto) {

        String desc = "";//字符串格式：“手动档｜准驾A2照｜床位1个”  //stone
        //1手动 2自动 3无动力
        if (dto.getGearBox() != null) {
            if (dto.getGearBox().intValue() == 1) {
                desc += "手动" + "档|";
            } else if (dto.getGearBox().intValue() == 2) {
                desc += "自动" + "档|";
            } else if (dto.getGearBox().intValue() == 3) {
                desc += "无动力" + "|";
            } else {
                desc += "手动" + "档|";
            }
        }
        //驾照
        if (dto.getDrivingLicense() != null) {
            if (dto.getDrivingLicense().contains("照")) {
                desc += "准驾" + dto.getDrivingLicense() + "|";
            } else {
                desc += "准驾" + dto.getDrivingLicense() + "照|";
            }
        }
        if (dto.getBedNumber() != null) {
            desc += "床位" + dto.getBedNumber() + "个|";
        }
        if (desc.length() > 0) {
            desc = desc.substring(0, desc.length() - 1);
        }
        dto.setTitle(desc);

        return dto;
    }
}
